package com.xuzm.netty.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class ExecutorConfig {

    private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
    private int corePoolSize = 5;
    private int maxPoolSize = 10;
    private int queueCapacity = 99999;
    private String namePrefix = "async-";

    @Bean(name = "asyncSchedule")
    public ThreadPoolTaskScheduler asyncServiceTaskScheduler(){
        logger.info("start asyncServiceTaskScheduler");
        // Spring 默认配置是核心线程数大小为1，最大线程容量大小不受限制，队列容量也不受限制。
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        // 核心线程数
        int corePoolSize = 5;
        scheduler.setPoolSize(corePoolSize);
        scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        scheduler.setThreadNamePrefix("async-scheduler-");
        //表明是否等待所有线程执行完任务
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        //等待的时间，超过这个时间就强制销毁，因为不能无限的等待下去以确保应用最后能够被关闭
        scheduler.setAwaitTerminationSeconds(60);
        scheduler.setRemoveOnCancelPolicy(Boolean.TRUE);
        scheduler.setErrorHandler((throwable) ->{
            logger.error("====" + throwable.getMessage() + "====", throwable);
        });
        scheduler.initialize();
        return scheduler;
    }

    @Bean(name = "asyncTask")
    public ThreadPoolTaskExecutor asyncServiceExecutor(){
        logger.info("start asyncServiceExecutor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(namePrefix);

        // rejection-policy: 当pool已经达到max size的时候，如何处理新任务
        // CALLER_RUNS: 不在新线程中执行任务，而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
}
